import SparkMD5 from 'spark-md5'

export const CHUNK_SIZE = 1024 * 1024 * 20

/**
 * 计算文件的hash值，计算的时候并不是根据所用的切片的内容去计算的，那样会很耗时间，我们采取下面的策略去计算：
 * 1. 第一个和最后一个切片的内容全部参与计算
 * 2. 中间剩余的切片我们分别在前面、后面和中间取2个字节参与计算
 * 这样做会节省计算hash的时间
 */
export const createChunksHash = async (fileChunks: Blob[], chunkSize = CHUNK_SIZE) => {
  return new Promise((resolve) => {
    const spark = new SparkMD5.ArrayBuffer()
    const chunks: Blob[] = []

    fileChunks.forEach((chunk, index) => {
      if (index === 0 || index === fileChunks.length - 1) {
        // 1. 第一个和最后一个切片的内容全部参与计算
        chunks.push(chunk)
      } else {
        // 2. 中间剩余的切片我们分别在前面、后面和中间取2个字节参与计算
        // 前面的2字节
        chunks.push(chunk.slice(0, 2))
        // 中间的2字节
        chunks.push(chunk.slice(chunkSize / 2, chunkSize / 2 + 2))
        // 后面的2字节
        chunks.push(chunk.slice(chunkSize - 2, chunkSize))
      }
    })

    const reader = new FileReader()
    reader.readAsArrayBuffer(new Blob(chunks))
    reader.onload = (e: ProgressEvent<FileReader>) => {
      spark.append(e?.target?.result as ArrayBuffer)
      resolve(spark.end())
    }
  })
}

// 计算文件hash值
export const createFileHash = (file: File) => {
  return new Promise((resolve, reject) => {
    const spark = new SparkMD5.ArrayBuffer()
    const fileReader = new FileReader()
    fileReader.onload = (e: ProgressEvent<FileReader>): void => {
      spark.append(e.target?.result)
      resolve(spark.end())
    }
    fileReader.onerror = () => {
      reject('')
    }
    fileReader.readAsArrayBuffer(file)
  })
}

/**
 * 创建文件分片
 * @param file
 * @returns
 */
export const createFileChunks = (file: File, chunkSize = CHUNK_SIZE) => {
  const fileChunks: Blob[] = []
  let cur = 0
  while (cur < file.size) {
    fileChunks.push(file.slice(cur, cur + chunkSize))
    cur += chunkSize // chunkSize为分片的大小
  }

  return fileChunks
}

export function localDownload(file: File, name: string) {
  const a = document.createElement('a')
  a.setAttribute('download', name)
  a.href = URL.createObjectURL(file)
  a.click()
}

export const getChunkArgs = (size: number, chunkSize = CHUNK_SIZE) => {
  const ret: { offset: number; length: number }[] = []
  let count = 0
  while (size > chunkSize) {
    size = size - chunkSize
    ret.push({ offset: count * chunkSize, length: chunkSize })
    count++
  }
  if (size > 0) ret.push({ offset: count * chunkSize, length: size })

  return ret
}

export const formatSize = (size: number) => {
  const rate = 1024
  if(size < rate) return `${size}字节`
  if(size < rate ** 2) return `${(size / rate).toFixed(0)}K`
  if(size < rate ** 3) return `${(size / (rate ** 2)).toFixed(0)}M`
  if(size < rate ** 4) return `${(size / (rate ** 3)).toFixed(2)}G`

  return `${(size / (rate ** 4)).toFixed(2)}T`
}

export const getFileExt = (fileName: string) => {
  const pos = fileName.lastIndexOf('.')
  return fileName.substring(pos + 1)
}

export const getRealName = (fileName: string) => {
  fileName = fileName.substring(fileName.lastIndexOf('/') + 1)
  const ext = getFileExt(fileName)
  const s = fileName.substring(0, fileName.lastIndexOf('.'))
  return `${s.substring(0, s.lastIndexOf('.'))}.${ext}`
}